package xib.parserTools.data;

import java.util.ArrayList;
import xib.parserTools.interfaces.IPageData;
import xib.parserTools.interfaces.IPanelData;
import xib.utils.XibDataException;


/**
 * Implementation from the interface IPageData, this implementation is
 * used to save the data from the source before to be processed by the core.
 * @author xavierds
 */
public final class PageData implements IPageData{

    /**
     * List of panels from the page.
     */
    private ArrayList<IPanelData> panels;

    /**
     * Fields with the heith and width of the Page.
     */
    private int height, width;

    /**
     * Field with the position of the Page.
     */
    private int position;

    /**
     * Field who indicates if the panel was validate.
     */
    private boolean validate;


    /**
     * Default Constructor of the PageData. It initialize the list of pages and
     * sets the others fields to null.
     */
    public PageData(){
        panels = new ArrayList<IPanelData>();
    }

    
    public int getHeight() {
        if(height <= 0)
            throwXibDataException(new IllegalStateException("The height " +
                    "has not been initialized properly."));
        return height;
    }


    public int getWidth() {
        if(width <= 0)
            throwXibDataException(new IllegalStateException("The width " +
                    "has not been initialized properly."));
        return width;
    }

    
    public int getPosition(){
            throwXibDataException(new IllegalStateException("The position " +
                    "has not been initialized properly."));
        return position;
    }


    public ArrayList<IPanelData> getPanels() {
        if(panels.isEmpty())
            throwXibDataException(new IllegalStateException("The list of " +
                    "IPanelData has not been initialized properly."));
        return panels;
    }


    public void setWidthAndHeight(int width, int height) {
        validate = false;
        if(height <= 0 || width <= 0)
            throwXibDataException(new IllegalArgumentException("The width " +
                    "and the height must be greater than 0."));
        this.height = height;
        this.width = width;
    }

    
    public void setPosition(int position){
        validate = false;
        if(position < 1)
            throwXibDataException(new IllegalArgumentException("The position" +
                    " must be greater than 1."));
        this.position = position;
    }

    
    public void addPanel(IPanelData pd) {
        validate = false;
        if(pd == null){
            NullPointerException ex =  new NullPointerException("Panel " +
                    "wasn't initialized properly.");
            throw new XibDataException(ex);
        }
        if(panels.contains(pd)){
            IllegalArgumentException ex = new IllegalArgumentException("This " +
                    "panel is already present in this page.");
            throw new XibDataException(ex);
        }
        panels.add(pd);
    }

    
    public boolean validate(){
        if(!validate){
            if(width <= 0 || height <= 0)
                throwXibDataException(new IllegalStateException("Some " +
                        "values of the panel weren't correctly initialized."));


            //List of panels can't be 0.
            if(panels.isEmpty())
                throwXibDataException(new IllegalStateException("Page " +
                        "needs to have some panels assigned."));

            boolean panelsPosition[] = new boolean[panels.size() + 1];
            IPanelData  panel;

            //Verify panels specification.
            for(int i=0; i < panels.size(); i++){
                panel = panels.get(i);

                //Validate the panel himself.
                panel.validate();

                //Panel can't have a position higher than the number of panels.
                if(panel.getOrder() > panels.size())
                    throwXibDataException(new IllegalStateException("Some " +
                            "panels position are incorrect."));

                
                //Two panels can't have the same position.
                if(!panelsPosition[panel.getOrder()])
                    panelsPosition[panel.getOrder()] = true;
                else
                    throwXibDataException(new IllegalStateException("Two " +
                            "panels can't have the same position."));
            }
        validate = true;
        }

        return true;
    }

    /**
     * Throw a new XibDataException with the cause from the given.
     * @param cause
     */
    private void throwXibDataException(Throwable cause){
        throw new XibDataException("Error in the internal data of the source, " +
                "in the PageData."
                , cause);
    }

}
